﻿using System;
using System.Collections.Generic;
using System.Text;

/*
	Todo extract some base functionality
	06/07/2012: Added quickdiff to the Top left menu.
*/
namespace SqlServerDriver
{
	class SqlServerPopupBuilder
	{
		public SqlServerPopupBuilder()
		{
			this.IsDevelopmentDatabase = false;
		}
		public SqlServerPopupBuilder(bool isDevDb)
		{
			this.IsDevelopmentDatabase = isDevDb;
		}

		bool IsDevelopmentDatabase {get; set; }

        // standards used by this and broker
		public static DbViewDriver.CustomMenuItem AddItem(DbViewDriver.CustomMenuItem root, String menuText, DbView.Commands.Cmnd command)
        {
			DbViewDriver.CustomMenuItem newOne = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.item, menuText, command.ToString());
            root.AddItem(AddHelp(newOne, new DbView.Command(command)));
            return newOne;
        }

		public static DbViewDriver.CustomMenuItem AddHelp(DbViewDriver.CustomMenuItem item, DbView.Command command)
		{
			String help = DbView.CommandHelpRepository.Instance.GetHelp(command);
			item.Help = help;
            return item;
        }

		public DbViewDriver.CustomMenuItem AddMenu(DbViewDriver.CustomMenuItem root, String menuText)
        {
			DbViewDriver.CustomMenuItem newOne = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.menu, menuText);
            root.AddItem(newOne);
            return newOne;
        }

		public static DbViewDriver.CustomMenuItem AddCustomItem(DbViewDriver.CustomMenuItem root, String menuText, DbView.Command command)
        {
			DbViewDriver.CustomMenuItem newOne = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.item, menuText, command.ToXml());
            root.AddItem(AddHelp(newOne, command));
            return newOne;
        }
        public static void AddSeparator(DbViewDriver.CustomMenuItem root)
        {
            root.AddItem(new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.separator));
        }
		public static DbViewDriver.CustomMenuItem AddCustomMenuItem(DbViewDriver.CustomMenuItem menu, String text, String commandTag)
		{
			DbView.Command c = Cmd.MakeCommand(commandTag);
			DbViewDriver.CustomMenuItem newOne = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.item, text, c.ToXml());
			menu.AddItem(AddHelp(newOne, c));
			return newOne;
		}

		public static DbViewDriver.CustomMenuItem AddCustomMenuItem(DbViewDriver.CustomMenuItem menu, String text, String commandTag, int extraColumnNumber)
		{
			DbView.Command c = Cmd.MakeCommand(commandTag);
			DbViewDriver.CustomMenuItem newOne = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.item, text, c.ToXml());
			menu.AddItem(AddHelp(newOne, c));
			return newOne;
		}

		public static void AddProfile(DbViewDriver.CustomMenuItem root) { AddItem(root, "Profile", DbView.Commands.Cmnd.Profile); }
        public static void AddShowSql(DbViewDriver.CustomMenuItem root) // needs renaming
        {
			AddExportToExcel(root);
			DbViewDriver.CustomMenuItem item = AddItem(root, "Show Sql", DbView.Commands.Cmnd.ShowCommand);
			item.IsRowIndependent = true;
		}
        public static void AddExportToExcel(DbViewDriver.CustomMenuItem root)
        {
			DbViewDriver.CustomMenuItem item = AddItem(root, "Grid to Excel", DbView.Commands.Cmnd.Excel);
			item.IsRowIndependent = true;
		}
        /*
            standard popup offering of profile/show sql until you think of what else 
            to implement as a popup
        */
        public static void AppendDefault(DbViewDriver.CustomMenuItem root, bool withSeparator)
        {
            if (withSeparator) AddSeparator(root);
            AddProfile(root);
            AddShowSql(root);
        }
        
        public DbViewDriver.CustomMenuItem BuildPopupMenu(DbView.Command command)
		{
			DbViewDriver.CustomMenuItem root = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.menu);
			DbViewDriver.CustomMenuItem submenu;
			// [Specialise: popup menus]
			switch (command.Cmd)
			{
				case DbView.Commands.Cmnd.Tables:
					AddItem(root, "Data", DbView.Commands.Cmnd.TableData);
					AddItem(root, "Fields", DbView.Commands.Cmnd.Fields);
					if (this.IsDevelopmentDatabase)
					{
						AddSeparator(root);
						submenu = this.AddMenu(root, "Modify");
						AddItem(submenu, "Truncate [ ]", DbView.Commands.Cmnd.Cleartable);
						AddItem(submenu, "Drop [ ]", DbView.Commands.Cmnd.Droptable);
						AddCustomMenuItem(submenu, "Reset AutoIncrement", Cmd.ResetAuto);
					}
					AddSeparator(root);
					AddItem(root, "Dependencies", DbView.Commands.Cmnd.Dependencies);
					AddItem(root, "Find in Source", DbView.Commands.Cmnd.SearchSource);
					AddSeparator(root);
					AddCustomMenuItem(root, "Descriptions", Cmd.Descriptions); // see
					AddSeparator(root);
					AddItem(root, "Script Schema", DbView.Commands.Cmnd.TableSource);
					AddCustomMenuItem(root, "Script POCO Class", Cmd.ScriptClass);
					AddCustomMenuItem(root, "Script Compare", Cmd.ScriptCompare);
					AddCustomMenuItem(root, "Copy", Cmd.CopyTable); // see
					AddItem(root, "Export", DbView.Commands.Cmnd.Export);
					AddItem(root, "Import", DbView.Commands.Cmnd.Import);
					AddSeparator(root);
					if (this.IsDevelopmentDatabase)
						AddCustomMenuItem(root, "New Table",Cmd.CreateTable).IsRowIndependent = true;
					AddCustomMenuItem(root, "Physical Sizes", Cmd.TableSizes).IsRowIndependent = true; 
					this.AddQuickDiffMenuItem(root, command.Cmd); // see
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.TableData:
					AddItem(root, "Profile All", DbView.Commands.Cmnd.Profile);
					this.AddProfileDataOnly(root);
					AddItem(root, "Fields", DbView.Commands.Cmnd.Fields).IsRowIndependent = true;
					AddItem(root, "Edit View", DbView.Commands.Cmnd.EditView).IsRowIndependent = true;
					this.AddScriptItem(root, "Script Data", "DATA").IsRowIndependent = true;
					AddItem(root, "Export", DbView.Commands.Cmnd.Export).IsRowIndependent = true; 
					if (this.IsDevelopmentDatabase)
					{
						AddSeparator(root);
						AddItem(root, "Delete All Data", DbView.Commands.Cmnd.Cleartable).IsRowIndependent = true;
					}
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Fields:
					AddProfile(root);
					AddItem(root, "Find in Source", DbView.Commands.Cmnd.SearchSource);
					if (this.IsDevelopmentDatabase)
					{
						AddItem(root, "Modify", DbView.Commands.Cmnd.ChangeColumn);
						AddItem(root, "Remove", DbView.Commands.Cmnd.RemoveColumn);
						AddCustomMenuItem(root, "Add Foreign Key", Cmd.AddFK); // see
						AddSeparator(root);
						AddItem(root, "Add New Field", DbView.Commands.Cmnd.AddColumn).IsRowIndependent = true;
					}
					AddSeparator(root);
					AddItem(root, "Script Schema", DbView.Commands.Cmnd.TableSource).IsRowIndependent = true;
					AddSeparator(root);
					AddShowSql(root);
					break;

				case DbView.Commands.Cmnd.Views:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ViewSource);
					AddItem(root, "Data", DbView.Commands.Cmnd.TableData);
					AddItem(root, "Fields", DbView.Commands.Cmnd.Fields);
					AddSeparator(root);
					AddItem(root, "Dependencies", DbView.Commands.Cmnd.Dependencies);
					AddItem(root, "Find In Source", DbView.Commands.Cmnd.SearchSource);
					AddSeparator(root);
					AddCustomMenuItem(root, "Copy", Cmd.CopyView); 
					AddSeparator(root);
					this.AddQuickDiffMenuItem(root, command.Cmd); // see
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Procedures:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddItem(root, "Dependencies", DbView.Commands.Cmnd.Dependencies);
					AddItem(root, "Find In Source", DbView.Commands.Cmnd.SearchSource);
					AddSeparator(root);
					AddCustomMenuItem(root, "Copy", Cmd.CopyProc); 
					AddSeparator(root);
					this.AddQuickDiffMenuItem(root, command.Cmd); // see
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Functions:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddItem(root, "Dependencies", DbView.Commands.Cmnd.Dependencies);
					AddItem(root, "Find In Source", DbView.Commands.Cmnd.SearchSource);
					AddSeparator(root);
					this.AddQuickDiffMenuItem(root, command.Cmd); // see
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Triggers:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddItem(root, "Dependencies", DbView.Commands.Cmnd.Dependencies);
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Aggregate:
					this.AddAggregateShowTableData(root, "Show Data");
					AppendDefault(root, true);
					break;
				case DbView.Commands.Cmnd.ProcedureSourceSearch:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.ViewSourceSearch:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.FunctionSourceSearch:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.TableFieldSearch:
					AddItem(root, "Fields", DbView.Commands.Cmnd.Fields);
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.AllSourceSearch:
					AddItem(root, "View Full Source", DbView.Commands.Cmnd.ShowSource);
					AddSeparator(root);
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Dependencies:
					AddItem(root, "View Source", DbView.Commands.Cmnd.ShowSource);
					AddCustomMenuItem(root, "Show tree", Cmd.DependencyTree);
					AppendDefault(root, true);
					break;
				case DbView.Commands.Cmnd.ForeignKeys:
					AddProfile(root);
					if (this.IsDevelopmentDatabase)
					{
						AddSeparator(root);
						AddCustomMenuItem(root, "Disable", Cmd.DisableFK);
						AddCustomMenuItem(root, "Enable", Cmd.EnableFK);
						AddCustomMenuItem(root, "Remove", Cmd.DelFK);
						AddSeparator(root);
					}
					submenu = this.AddMenu(root, "Script");
					this.AddScriptItem(submenu, "Create this FK", "FK");
					this.AddScriptItem(submenu, "All Keys", "FKALL");
					this.AddScriptItem(submenu, "Remove this FK", "XFK");
					this.AddScriptItem(submenu, "Remove All Keys", "XFKALL");
					AddSeparator(root);
					this.AddQuickDiffMenuItem(root, command.Cmd); // see
					AddShowSql(root);
					break;
				case DbView.Commands.Cmnd.Permissions:
					this.AddPermissionSummary(root, "Summary");
					AppendDefault(root, true);
					break;
				// [Specialise: extension command popup menus]
				case DbView.Commands.Cmnd.Extension:
					switch (command.Name)
					{
						case Cmd.TableSizes:
							AddItem(root, "Data", DbView.Commands.Cmnd.TableData);
							AddItem(root, "Fields", DbView.Commands.Cmnd.Fields);
							AddSeparator(root);
							AddItem(root, "Dependencies", DbView.Commands.Cmnd.Dependencies);
							AddItem(root, "Find In Source", DbView.Commands.Cmnd.SearchSource);
							AddSeparator(root);
							AddCustomMenuItem(root, "Descriptions", Cmd.Descriptions); // see
							AddSeparator(root);
							AddItem(root, "Script Schema", DbView.Commands.Cmnd.TableSource);
							AddCustomMenuItem(root, "Copy", Cmd.CopyTable); // see
							AddSeparator(root);
							AddShowSql(root);
							break;
						case Cmd.Owners:
							AppendDefault(root, true);
							if (this.IsDevelopmentDatabase)
							{
								AddSeparator(root);
								AddCustomMenuItem(root, "Add Schema", Cmd.CreateSchema).IsRowIndependent = true;
								AddCustomMenuItem(root, "Remove Schema", Cmd.RemoveSchema);
							}
							break;
						case Cmd.Processes:
							AddCustomMenuItem(root, "Last Command", Cmd.LastProcessCommand);
							AppendDefault(root, true);
							break;
						case Cmd.Descriptions:
							AddCustomMenuItem(root, "Edit", Cmd.EditDescriptions); 
							AppendDefault(root, true);
							break;
						case Cmd.Jobs:
							AddCustomMenuItem(root, "Job Steps", Cmd.JobSteps); 
							AddCustomMenuItem(root, "Job History", Cmd.JobHistory); 
							AppendDefault(root, true);
							break;
						case Cmd.Publications:
							this.AddArticlesItem(root, "Articles");
							AppendDefault(root, true);
							break;
						case Cmd.ExtendedProperties:
							AddCustomMenuItem(root, "Details", Cmd.PropertyValues); 
							AppendDefault(root, true);
							break;
						case Cmd.PropertyValues:
							if (IsTableDescriptionProperties(command))
							{
								if (IsMSDescriptionProperty(command))
								{
									AddCustomMenuItem(root, "Edit Property", Cmd.Descriptions); // possibly expand this.
									AddSeparator(root);
								}
								AddCustomMenuItem(root, "Script All", Cmd.ScriptAddAllTableProperties).IsRowIndependent = true;
								AddCustomMenuItem(root, "Script This", Cmd.ScriptAddTableProperty);
								AddCustomMenuItem(root, "Script Drop", Cmd.DropTableProperty);
								AddSeparator(root);
							}
							else if (IsColumnDescriptionProperties(command))
							{
								AddCustomMenuItem(root, "Edit", Cmd.EditDescriptions); 
								AddCustomMenuItem(root, "Script All", Cmd.ScriptAddAllColumnProperties).IsRowIndependent = true;
								AddCustomMenuItem(root, "Script Table", Cmd.ScriptAddTableColumnProperty);
								AddCustomMenuItem(root, "Script Drop ", Cmd.DropColumnProperty); 
								AddSeparator(root);
							}
							AppendDefault(root, false);
							break;
						default: 
							// test for service broker sub-system
							if (SqlServerBrokerPopupBuilder.IsBrokerCommand(command))
								SqlServerBrokerPopupBuilder.BuildPopupMenu(command, root);
							else 
								AppendDefault(root, false);break;
					}
					break;
				default:
					AppendDefault(root, false);
					break;
			}
			AddHelp(root);
			return root;
		}

		private bool IsColumnDescriptionProperties(DbView.Command command)
		{
			// param 0 must be COLUMN
			String itemType = command[DbView.Command.TableParameterName(0)]; 
			return (itemType == "COLUMN") ? true : false;
		}

		private bool IsTableDescriptionProperties(DbView.Command command)
		{
			// param 0 must be USER_TABLE
			String itemType = command[DbView.Command.TableParameterName(0)]; 
			return (itemType == "USER_TABLE") ? true : false;
		}
		private bool IsMSDescriptionProperty(DbView.Command command)
		{
			String propertyName = command["PROP"]; 
			return (propertyName == "MS_Description") ? true : false;
		}

		private void AddHelp(DbViewDriver.CustomMenuItem root)
		{
		}
		
		/*
			Custom construction
		*/ 
		void AddProfileDataOnly(DbViewDriver.CustomMenuItem root)
		{
			DbView.Command command = new DbView.Command(DbView.Commands.Cmnd.Profile);
			command.AddParam("NOTEMPTY", "Y");
			AddCustomItem(root, "Profile Data only", command);
		}
		
		DbViewDriver.CustomMenuItem AddScriptItem(DbViewDriver.CustomMenuItem root, String menuText, String objectType)
		{
			DbView.Command command = new DbView.Command(DbView.Commands.Cmnd.ShowSource);
			command.AddParam("TYPE", objectType);
			return AddCustomItem(root, menuText, command);
		}

		void AddArticlesItem(DbViewDriver.CustomMenuItem root, String menuText)
		{
			DbView.Command command = Cmd.MakeCommand(Cmd.Articles);
			command.AddParam("PUB", "Y");  // flag to use the table parameter
			AddCustomItem(root, menuText, command);
		}
	
		void AddShowData(DbViewDriver.CustomMenuItem root, String menuText, int targetColumn)
		{
			DbView.Command command = new DbView.Command(DbView.Commands.Cmnd.ShowProfileData, "", DbView.Command.CommandAction.sysaction);
			command.AddParam("DATACOL", targetColumn.ToString());
		}

		void AddAggregateShowTableData(DbViewDriver.CustomMenuItem root, String menuText)
		{
			DbView.Command command = new DbView.Command(DbView.Commands.Cmnd.TableData);
			command.AddParam("CALLER", DbView.Commands.Cmnd.Aggregate.ToString());
			AddCustomItem(root, menuText, command);
		}

		void AddPermissionSummary(DbViewDriver.CustomMenuItem root, String menuText)
		{
			DbView.Command command = new DbView.Command(DbView.Commands.Cmnd.Permissions);
			command.AddParam("SUMMARY", "Y");
			AddCustomItem(root, menuText, command);
		}

		private void AddQuickDiffMenuItem(DbViewDriver.CustomMenuItem root, DbView.Commands.Cmnd callerCmd)
		{
			DbView.Command c = Cmd.MakeCommand(Cmd.QuickDiffDialog);
			c.AddParam("CALLER", callerCmd.ToString());
			AddCustomItem(root, "Quick Diff", c).IsRowIndependent = true;
		}
		private void AddRemoveSchemaMenuItem(DbViewDriver.CustomMenuItem root, DbView.Commands.Cmnd callerCmd)
		{
			DbView.Command c = Cmd.MakeCommand(Cmd.RemoveSchema);
			c.AddParam("CALLER", callerCmd.ToString());
			AddCustomItem(root, "Quick Diff", c).IsRowIndependent = true;
		}

		// todo: convert these to Cmd. Strings.
		public DbViewDriver.CustomMenuItem BuildCustomMenu()
		{
			DbViewDriver.CustomMenuItem menu = new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.menu, "Sql Server", "");
			AddCustomMenuItem(menu, "Owners", Cmd.Owners);
			AddCustomMenuItem(menu, "Processes", Cmd.Processes);
			AddCustomMenuItem(menu, "Users", Cmd.Users);
			AddCustomMenuItem(menu, "Locks", Cmd.Locks);
			AddCustomMenuItem(menu, "Jobs", Cmd.Jobs);
			AddCustomMenuItem(menu, "Linked Servers", Cmd.LinkedServers);
			menu.AddItem(new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.separator));
			AddCustomMenuItem(menu, "Publications", Cmd.Publications);
			AddCustomMenuItem(menu, "Articles", Cmd.Articles);
			menu.AddItem(new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.separator));
			AddCustomMenuItem(menu, "Extended Properties", Cmd.ExtendedProperties);
			AddCustomMenuItem(menu, "Service Broker", Cmd.BrokerQueues);
			menu.AddItem(new DbViewDriver.CustomMenuItem(DbViewDriver.CustomMenuItem.ItemType.separator));
			AddCustomMenuItem(menu, "Profiler...", Cmd.LaunchProfiler);
			return menu;
		}
	}
}
